Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
The c12 npm package is a configuration loader and manager that helps in loading, merging, and managing configurations from various sources such as files, environment variables, and more. It is designed to be flexible and easy to use, making it suitable for a wide range of applications.
Loading Configuration from Files
This feature allows you to load configuration from files. The `loadConfig` function reads configuration files based on the provided options such as the name of the application and the current working directory.
const { loadConfig } = require('c12');
async function loadConfigExample() {
const config = await loadConfig({
name: 'myapp',
cwd: process.cwd(),
rcFile: true
});
console.log(config);
}
loadConfigExample();
Merging Configurations
This feature allows you to merge configurations from different sources. The `loadConfig` function can take default configurations and override configurations, merging them into a single configuration object.
const { loadConfig } = require('c12');
async function mergeConfigExample() {
const config = await loadConfig({
name: 'myapp',
defaults: { key1: 'default1' },
overrides: { key2: 'override2' }
});
console.log(config);
}
mergeConfigExample();
Loading Configuration from Environment Variables
This feature allows you to load configuration from environment variables. The `loadConfig` function can be configured to read environment variables with a specific prefix and include them in the configuration object.
const { loadConfig } = require('c12');
async function envConfigExample() {
process.env.MYAPP_KEY = 'valueFromEnv';
const config = await loadConfig({
name: 'myapp',
envPrefix: 'MYAPP_'
});
console.log(config);
}
envConfigExample();
The 'config' package is a popular configuration management tool for Node.js applications. It allows you to define configurations for different environments and load them based on the current environment. Compared to c12, 'config' is more opinionated and structured, making it easier to manage complex configurations but less flexible in terms of merging and loading from multiple sources.
The 'dotenv' package loads environment variables from a .env file into process.env. It is simpler and more focused compared to c12, which offers more comprehensive configuration management capabilities including merging configurations from multiple sources.
The 'rc' package is a non-opinionated configuration loader that reads configuration from various sources like files, environment variables, and command-line arguments. It is similar to c12 in terms of flexibility but lacks some of the advanced features like merging configurations and handling defaults and overrides.
c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
.js
, .ts
, .mjs
, .cjs
, .mts
, .cts
.json
config loader with unjs/jiti.jsonc
, .json5
, .yaml
, .yml
, .toml
config loader with unjs/confbox.config/
directory support following config dir proposal.rc
config support with unjs/rc9.env
support with dotenvpackage.json
fileInstall package:
# ✨ Auto-detect
npx nypm install c12
# npm
npm install c12
# yarn
yarn add c12
# pnpm
pnpm install c12
# bun
bun install c12
Import:
ESM (Node.js, Bun)
import { loadConfig, watchConfig } from "c12";
CommonJS (Legacy Node.js)
const { loadConfig, watchConfig } = require("c12");
Load configuration:
// Get loaded config
const { config } = await loadConfig({});
// Get resolved config and extended layers
const { config, configFile, layers } = await loadConfig({});
c12 merged config sources with unjs/defu by below order:
package.json
cwd
Resolve configuration from this working directory. The default is process.cwd()
name
Configuration base name. The default is config
.
configFile
Configuration file name without extension. Default is generated from name
(f.e., if name
is foo
, the config file will be => foo.config
).
Set to false
to avoid loading the config file.
rcFile
RC Config file name. Default is generated from name
(name=foo => .foorc
).
Set to false
to disable loading RC config.
globalRC
Load RC config from the workspace directory and the user's home directory. Only enabled when rcFile
is provided. Set to false
to disable this functionality.
dotenv
Loads .env
file if enabled. It is disabled by default.
packageJson
Loads config from nearest package.json
file. It is disabled by default.
If true
value is passed, c12 uses name
field from package.json
.
You can also pass either a string or an array of strings as a value to use those fields.
defaults
Specify default configuration. It has the lowest priority and is applied after extending config.
defaultConfig
Specify default configuration. It is applied before extending config.
overrides
Specify override configuration. It has the highest priority and is applied before extending config.
omit$Keys
Exclude environment-specific and built-in keys start with $
in the resolved config. The default is false
.
jiti
Custom unjs/jiti instance used to import configuration files.
jitiOptions
Custom unjs/jiti options to import configuration files.
giget
Options passed to unjs/giget when extending layer from git source.
merger
Custom options merger function. Default is defu.
Note: Custom merge function should deeply merge options with arguments high -> low priority.
envName
Environment name used for environment specific configuration.
The default is process.env.NODE_ENV
. You can set envName
to false
or an empty string to disable the feature.
If resolved config contains a extends
key, it will be used to extend the configuration.
Extending can be nested and each layer can extend from one base or more.
The final config is merged result of extended options and user options with unjs/defu.
Each item in extends is a string that can be either an absolute or relative path to the current config file pointing to a config file for extending or the directory containing the config file.
If it starts with either github:
, gitlab:
, bitbucket:
, or https:
, c12 automatically clones it.
For custom merging strategies, you can directly access each layer with layers
property.
Example:
// config.ts
export default {
colors: {
primary: "user_primary",
},
extends: ["./theme"],
};
// config.dev.ts
export default {
dev: true,
};
// theme/config.ts
export default {
extends: "../base",
colors: {
primary: "theme_primary",
secondary: "theme_secondary",
},
};
// base/config.ts
export default {
colors: {
primary: "base_primary",
text: "base_text",
},
};
The loaded configuration would look like this:
const config = {
dev: true,
colors: {
primary: "user_primary",
secondary: "theme_secondary",
text: "base_text",
},
};
Layers:
[
{
config: {
/* theme config */
},
configFile: "/path/to/theme/config.ts",
cwd: "/path/to/theme ",
},
{
config: {
/* base config */
},
configFile: "/path/to/base/config.ts",
cwd: "/path/to/base",
},
{
config: {
/* dev config */
},
configFile: "/path/to/config.dev.ts",
cwd: "/path/",
},
];
You can also extend configuration from remote sources such as npm or github.
In the repo, there should be a config.ts
(or config.{name}.ts
) file to be considered as a valid config layer.
Example: Extend from a github repository
// config.ts
export default {
extends: "gh:user/repo",
};
Example: Extend from a github repository with branch and subpath
// config.ts
export default {
extends: "gh:user/repo/theme#dev",
};
Example: Extend a private repository and install dependencies:
// config.ts
export default {
extends: ["gh:user/repo", { auth: process.env.GITHUB_TOKEN, install: true }],
};
You can pass more options to giget: {}
in layer config.
Refer to unjs/giget for more information.
Users can define environment-specific configuration using these config keys:
$test: {...}
$development: {...}
$production: {...}
$env: { [env]: {...} }
c12 tries to match envName
and override environment config if specified.
Note: Environment will be applied when extending each configuration layer. This way layers can provide environment-specific configuration.
Example:
export default {
// Default configuration
logLevel: "info",
// Environment overrides
$test: { logLevel: "silent" },
$development: { logLevel: "warning" },
$production: { logLevel: "error" },
$env: {
staging: { logLevel: "debug" },
},
};
you can use watchConfig
instead of loadConfig
to load config and watch for changes, add and removals in all expected configuration paths and auto reload with new config.
onWatch
: This function is always called when config is updated, added, or removed before attempting to reload the config.acceptHMR
: By implementing this function, you can compare old and new functions and return true
if a full reload is not needed.onUpdate
: This function is always called after the new config is updated. If acceptHMR
returns true, it will be skipped.import { watchConfig } from "c12";
const config = watchConfig({
cwd: ".",
// chokidarOptions: {}, // Default is { ignoreInitial: true }
// debounce: 200 // Default is 100. You can set it to false to disable debounced watcher
onWatch: (event) => {
console.log("[watcher]", event.type, event.path);
},
acceptHMR({ oldConfig, newConfig, getDiff }) {
const diff = getDiff();
if (diff.length === 0) {
console.log("No config changed detected!");
return true; // No changes!
}
},
onUpdate({ oldConfig, newConfig, getDiff }) {
const diff = getDiff();
console.log("Config updated:\n" + diff.map((i) => i.toJSON()).join("\n"));
},
});
console.log("watching config files:", config.watchingFiles);
console.log("initial config", config.config);
// Stop watcher when not needed anymore
// await config.unwatch();
[!NOTE] This feature is experimental
Update or create a new configuration files.
Add magicast
peer dependency:
# ✨ Auto-detect
npx nypm install -D magicast
# npm
npm install -D magicast
# yarn
yarn add -D magicast
# pnpm
pnpm install -D magicast
# bun
bun install -D magicast
Import util from c12/update
const { configFile, created } = await updateConfig({
cwd: ".",
configFile: "foo.config",
onCreate: ({ configFile }) => {
// You can prompt user if wants to create a new config file and return false to cancel
console.log(`Creating new config file in ${configFile}...`);
return "export default { test: true }";
},
onUpdate: (config) => {
// You can update the config contents just like an object
config.test2 = false;
},
});
console.log(`Config file ${created ? "created" : "updated"} in ${configFile}`);
Published under the MIT license.
Made by @pi0 and community 💛
🤖 auto updated with automd
FAQs
Smart Config Loader
The npm package c12 receives a total of 675,284 weekly downloads. As such, c12 popularity was classified as popular.
We found that c12 demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.